/* =========================================
 *           好友管理子服务实现 
 * =========================================*/
#pragma once
#include <brpc/server.h>
#include <memory>
#include <string>
#include <sys/stat.h>
#include <unordered_set>
#include <vector>
#include "chat_session.hxx"
#include "chat_session_member.hxx"
#include "dms.hpp"
#include "etcd.hpp"
#include "channel.hpp"
#include "base.pb.h"
#include "friend.pb.h"
#include "message_storage.pb.h"
#include "friend_apply.hxx"
#include "user.pb.h"
#include "utils.hpp"
#include "odb_factory.hpp"
#include "chat_session_dao.hpp"
#include "chat_session_member_dao.hpp"
#include "user_relation_dao.hpp"
#include "friend_apply_dao.hpp"
#include "search_repo.hpp"
#include "logger.hpp"

namespace im_server {

class FriendServiceImpl;
class FriendServer;
class FriendServerBuilder;
using FriendServiceImplPtr = std::shared_ptr<FriendServiceImpl>;
using FriendServerPtr = std::shared_ptr<FriendServer>;
using FriendServerBuilderPtr = std::shared_ptr<FriendServerBuilder>;

class FriendServiceImpl : public im_proto::FriendService
{
    typedef google::protobuf::Map<std::string, im_proto::UserInfo> GPUserMap;
    typedef google::protobuf::RepeatedPtrField<im_proto::MessageInfo> GPMsgMap;
public:
    FriendServiceImpl(const shared::dal::ESClientPtr& esClient,
        const shared::dal::OdbPtr& mysqlClient,
        const shared::infra::RpcServiceManagerPtr& rpcServiceMgr,
        const std::string& userServiceName, const std::string& messageServiceName) 
        : esUser_(std::make_shared<shared::dal::UserSearch>(esClient))
        , chatSessionDao_(std::make_shared<shared::dal::ChatSessionDao>(mysqlClient))
        , chatSessionMemberDao_(std::make_shared<shared::dal::ChatSessionMemberDao>(mysqlClient))
        , userRelationDao_(std::make_shared<shared::dal::UserRelationDao>(mysqlClient))
        , friendApplyDao_(std::make_shared<shared::dal::FriendApplyDao>(mysqlClient))
        , rpcServiceMgr_(rpcServiceMgr)
        , userServiceName_(userServiceName) 
        , messageServiceName_(messageServiceName) {}

    void GetFriendList(::google::protobuf::RpcController* controller,
                       const ::im_proto::GetFriendListReq* request,
                       ::im_proto::GetFriendListRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 通过 userID 获取该用户的好友列表
        const std::string& userId = request->user_id();
        auto friendIdList = userRelationDao_->selectFriends(userId);
        // 2. rpc获取用户位置信息数据
        GPUserMap userInfoMap;
        if(_getUser(rid, friendIdList, userInfoMap) == false) {
            LOG_ERROR("{}: 获取批量用户信息失败!", rid);
            return errResp(response, "批量用户信息获取失败");
        }
        // 3. 组织响应, 将好友列表返回网关
        response->set_success(true);
        for(auto& [id, info] : userInfoMap) {
            im_proto::UserInfo* userInfo = response->add_friend_list();
            userInfo->CopyFrom(info);
        }
    }
    void FriendRemove(::google::protobuf::RpcController* controller,
                       const ::im_proto::FriendRemoveReq* request,
                       ::im_proto::FriendRemoveRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取请求用户和被执行用户
        const std::string& reqId = request->req_user_id();
        const std::string& recvId = request->recv_user_id();
        // 2. 删除用户关系，删除对应会话及该会话关联成员
        if(userRelationDao_->remove(reqId, recvId) == false) {
            LOG_ERROR("删除好友关系{}-{}失败!", reqId, recvId);
            return errResp(response, "删除好友关系失败");
        }
        if(chatSessionDao_->remove(reqId, recvId) == false) {
            LOG_ERROR("删除好友{}-{}聊天会话失败!",  reqId, recvId);
            return errResp(response, "删除好友会话失败");
        }
        // 3. 组织响应返回网关
        response->set_success(true);
    }
    void FriendAdd(::google::protobuf::RpcController* controller,
                       const ::im_proto::FriendAddReq* request,
                       ::im_proto::FriendAddRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取请求用户和被申请用户 && 用户关系校验
        const std::string& reqId = request->req_user_id();
        const std::string& recvId = request->recv_user_id();
        if(userRelationDao_->exists(reqId, recvId)) {
            LOG_ERROR("好友申请失败, {}-{}已经是好友关系!", reqId, recvId);
            return errResp(response, "两者已经是好友关系");
        }
        // 2. 检查是否曾发起申请, 没有则添加申请记录
        if(friendApplyDao_->exists(reqId, recvId)) {
            LOG_ERROR("好友申请失败, {}用户已经向{}用户发起过申请!", reqId, recvId);
            return errResp(response, "已经发起过申请了");
        }
        const std::string& eventId = shared::Uuid::createUuid();
        entity::FriendApply friendApply(eventId, reqId, recvId);
        if(friendApplyDao_->insert(friendApply) == false) {
            LOG_ERROR("向数据新增申请记录失败{}-{}!", reqId, recvId);
            return errResp(response, "向数据新增申请记录失败");        
        }
        // 3. 组织响应，将事件 ID 信息响应给网关
        response->set_success(true);
        response->set_notify_event_id(eventId);
    }
    void FriendAddProcess(::google::protobuf::RpcController* controller,
                       const ::im_proto::FriendAddProcessReq* request,
                       ::im_proto::FriendAddProcessRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取请求用户和被申请用户
        const std::string& reqId = request->req_user_id();
        const std::string& recvId = request->recv_user_id();
        // 2. 申请事件表中查询是否存在该申请
        if(!friendApplyDao_->exists(reqId, recvId)) {
            LOG_ERROR("{}-{}好友申请事件不存在!", reqId, recvId);
            return errResp(response, "好友申请事件不存在");
        }
        // 3. 用户关系校验（互相加好友的情况）
        if(userRelationDao_->exists(reqId, recvId)) {
            LOG_ERROR("{}-{}已经是好友关系!", reqId, recvId);
            return errResp(response, "两者已经是好友关系");
        }
        // 4. 同意申请，则新增好友关系, 新增会话记录及会话相应成员
        std::string sessionId;
        if(request->agree()) {
            if(userRelationDao_->insert(reqId, recvId) == false) {
                LOG_ERROR("向数据库新增好友{}-{}关系失败!", reqId, recvId);
                return errResp(response, "向数据库新增好友关系失败"); 
            } 
            sessionId = shared::Uuid::createUuid();
            entity::ChatSession chatSession(sessionId, "", entity::ChatSessionType::SINGLE);
            if(chatSessionDao_->insert(chatSession) == false) {
                LOG_ERROR("向数据库新增会话信息({})失败!", sessionId);
                return errResp(response, "向数据库新增会话信息失败"); 
            }
            if(!chatSessionMemberDao_->insert(sessionId, reqId) ||
               !chatSessionMemberDao_->insert(sessionId, recvId)) {
                LOG_ERROR("向数据库新增会话成员{}-{}关系失败!", reqId, recvId);
                return errResp(response, "向数据库新增会话成员失败"); 
            }
        }
        // 4-1 删除申请事件记录
        if(friendApplyDao_->remove(reqId, recvId) == false) {
            LOG_ERROR("从数据库删除好友申请事件{}-{}失败!", reqId, recvId);
            return errResp(response, "从数据库删除好友申请事件失败"); 
        }
        // 5. 组织响应, 将生成的会话ID返回网关
        response->set_success(true);
        response->set_new_session_id(sessionId);
    }
    void FriendSearch(::google::protobuf::RpcController* controller,
                       const ::im_proto::FriendSearchReq* request,
                       ::im_proto::FriendSearchRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取请求用户/搜索关键字
        const std::string& userId = request->user_id();
        const std::string& searchKey = request->search_key();
        // 2. 获取该请求用户的好友列表
        auto friendList = userRelationDao_->selectFriends(userId);
        // 3. 通过es索引搜索好友(同时过滤掉自己 && 好友)
        friendList.emplace_back(userId);
        std::unordered_set<std::string> userIdSet;
        auto userList = esUser_->search(searchKey, friendList);
        for(auto& user : userList) {
            userIdSet.emplace(user.userId());
        }
        // 4. rpc获取用户信息数据
        GPUserMap userInfoMap;
        if(_getUser(rid, {userIdSet.begin(), userIdSet.end()}, userInfoMap) == false) {
            LOG_ERROR("{}: 获取批量用户信息失败!", rid);
            return errResp(response, "批量用户信息获取失败");
        }
        // 5. 组织响应，将搜索到的用户列表响应给网关
        response->set_success(true);
        for(auto& [id, info] : userInfoMap) {
            im_proto::UserInfo* userInfo = response->add_user_info();
            userInfo->CopyFrom(info);
        }
    }
    void GetChatSessionList(::google::protobuf::RpcController* controller,
                       const ::im_proto::GetChatSessionListReq* request,
                       ::im_proto::GetChatSessionListRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 从数据库获取单聊/群聊会话列表
        const std::string& userId = request->user_id();
        auto singleList = chatSessionDao_->selectAllSingleSession(userId);
        auto groupList = chatSessionDao_->selectAllGroupSession(userId);
        // 2. rpc 获取用户信息
        std::vector<std::string> friendIdList;
        friendIdList.reserve(singleList.size());
        for(auto& session : singleList) {
            friendIdList.emplace_back(session.friendId);
        }
        GPUserMap userInfoMap;
        if(_getUser(rid, friendIdList, userInfoMap) == false) {
            LOG_ERROR("{}: 获取批量用户信息失败!", rid);
            return errResp(response, "批量用户信息获取失败");
        }
        // 3. 组织响应
        for(auto& session : singleList) {
            // 3-1 构造会话信息
            auto userInfo = userInfoMap.at(session.friendId);
            im_proto::ChatSessionInfo* chatSessionInfo = response->add_chat_session_info_list();;
            chatSessionInfo->set_single_chat_friend_id(session.friendId);
            chatSessionInfo->set_chat_session_id(session.chatSessionId);
            chatSessionInfo->set_chat_session_name(userInfo.nickname());
            chatSessionInfo->set_avatar(userInfo.avatar());
            // 3-2 rpc 获取最近一条消息
            im_proto::MessageInfo messageInfo;
            if(_getMessage(rid, session.chatSessionId, messageInfo) == false) {
                LOG_ERROR("[{}] 获取会话({} {})最近消息失败", rid, session.chatSessionId, session.friendId);
                continue;
            }
            chatSessionInfo->mutable_prev_message()->CopyFrom(messageInfo);
        }
        for(auto& session : groupList) {
            // 3-1 构造会话信息
            im_proto::ChatSessionInfo* chatSessionInfo = response->add_chat_session_info_list();;
            chatSessionInfo->set_chat_session_id(session.chatSessionId);
            chatSessionInfo->set_chat_session_name(session.chatSessionName);
            // 3-2 rpc 获取最近一条消息
            im_proto::MessageInfo messageInfo;
            if(_getMessage(rid, session.chatSessionId, messageInfo) == false) {
                LOG_ERROR("[{}] 获取会话({} {})最近消息失败", rid, session.chatSessionId, session.chatSessionName);
                continue;
            }
            chatSessionInfo->mutable_prev_message()->CopyFrom(messageInfo);
        }
        response->set_success(true);
        LOG_DEBUG("[{}] 获取用户({})会话列表成功", rid, userId);
    }
    // 更多的是指创建群聊会话(主动性)
    void ChatSessionCreate(::google::protobuf::RpcController* controller,
                       const ::im_proto::ChatSessionCreateReq* request,
                       ::im_proto::ChatSessionCreateRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取会话名称, 成员ID列表
        const std::string& sessionName = request->chat_session_name();
        auto memberIdList = request->member_id_list();
        // 2. 生成会话ID、新增会话记录 && 新增该会话的成员
        const std::string& sessionId = shared::Uuid::createUuid();
        entity::ChatSession chatSession(sessionId, sessionName, entity::ChatSessionType::GROUP);
        if(chatSessionDao_->insert(chatSession) == false) {
            LOG_ERROR("{}: 向数据库新增群聊会话({}-{})失败", rid, sessionId, sessionName);
            return errResp(response, "向数据库新增群聊会话失败");    
        }
        std::pair<std::string, std::vector<std::string>> memberList;
        memberList.second.reserve(memberIdList.size());
        memberList.first = sessionId;
        for(auto& memberId : memberIdList) {
            memberList.second.emplace_back(memberId);
        }
        if(chatSessionMemberDao_->insert(memberList) == false) {
            LOG_ERROR("{}: 向群聊会话({})新增成员失败", rid, sessionId, sessionName);
            return errResp(response, "向群聊会话新增成员失败");   
        }
        // 3. 组织响应
        response->set_success(true);
        auto chatSessionInfo = response->mutable_chat_session_info();
        chatSessionInfo->set_chat_session_id(sessionId);
        chatSessionInfo->set_chat_session_name(sessionName);
    }
    // 获取群聊成员信息
    void GetChatSessionMember(::google::protobuf::RpcController* controller,
                       const ::im_proto::GetChatSessionMemberReq* request,
                       ::im_proto::GetChatSessionMemberRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取会话ID, 数据库获取成员Id列表 
        const std::string& sessionId = request->chat_session_id();
        auto memberIdList = chatSessionMemberDao_->selectMembers(sessionId);
        // 2. rpc 获取用户信息
        GPUserMap userInfoMap;
        if(_getUser(rid, memberIdList, userInfoMap) == false) {
            LOG_ERROR("{}: 获取批量用户信息失败!", rid);
            return errResp(response, "批量用户信息获取失败");
        }
        // 3. 组织响应
        for(auto& userId : memberIdList) {
            response->add_member_info_list()->CopyFrom(userInfoMap.at(userId));            
        }
        response->set_success(true);
    }
    // 获取待处理的好友申请列表
    void GetPendingFriendEventList(::google::protobuf::RpcController* controller,
                       const ::im_proto::GetPendingFriendEventListReq* request,
                       ::im_proto::GetPendingFriendEventListRsp* response,
                       ::google::protobuf::Closure* done)
    {
        const std::string& rid = request->request_id(); 
        brpc::ClosureGuard rpc_guard(done);
        response->set_request_id(request->request_id());

        // 1. 获取请求用户ID、从数据库中获取申请记录(只要记录还在, 就代表没处理)
        const std::string& userId = request->user_id();
        auto applyIdList = friendApplyDao_->selectFriendApply(userId);
        // 2. rpc获取用户信息数据
        GPUserMap userInfoMap;
        if(_getUser(rid, applyIdList, userInfoMap) == false) {
            LOG_ERROR("{}: 获取批量用户信息失败!", rid);
            return errResp(response, "批量用户信息获取失败");
        }
        // 3. 组织响应，将申请事件列表响应给网关
        response->set_success(true);
        for(auto& [id, info] : userInfoMap) {
            im_proto::FriendEvent* event = response->add_event();
            event->mutable_sender()->CopyFrom(info);
        }
    }
private:
    bool _getMessage(const std::string& rid, std::string& sessionId, im_proto::MessageInfo& respMessageInfo)
    {
        auto channel = rpcServiceMgr_->choose(messageServiceName_);
        if(!channel) {
            LOG_ERROR("{}-{} 消息存储子服务节点不存在!", rid, messageServiceName_);
            return false;
        }  
        // 2-1 构造请求体 && 通过信道发起服务请求
        im_proto::GetRecentHisMsgReq req;
        req.set_request_id(rid);
        req.set_chat_session_id(sessionId);
        req.set_msg_count(1);

        brpc::Controller ctl;
        im_proto::GetRecentHisMsgRsp resp;
        im_proto::MsgStorageService_Stub stub(channel.get());
        stub.GetRecentHisMsg(&ctl, &req, &resp, nullptr);
        if(ctl.Failed() || !resp.success()) {
            LOG_ERROR("{}: 获取会话({})的最近一条消息失败!", rid, sessionId, ctl.ErrorText());
            return false;
        }
        if(resp.msg_list().empty()) {
            return true; 
        }
        if(resp.msg_list().size() != 1) {
            LOG_ERROR("{}: 获取会话({})的最近一条消息数量异常!", rid, sessionId, ctl.ErrorText());
            return false;
        } 
        respMessageInfo = resp.msg_list().at(0);
        return true;
    }
    bool _getUser(const std::string& rid, const std::vector<std::string>& userIdList, GPUserMap& respUserInfoMap)
    {
        if(userIdList.empty()) {
            return true;
        }
        auto channel = rpcServiceMgr_->choose(userServiceName_);
        if(!channel) {
            LOG_ERROR("{}-{} 用户管理子服务节点不存在!", rid, userServiceName_);
            return false;
        }  
        // 2-1 构造请求体 && 通过信道发起服务请求
        im_proto::GetMultiUserInfoReq req;
        req.set_request_id(rid);
        for(auto& id : userIdList) {
            req.add_users_id(id);
        }
        brpc::Controller ctl;
        im_proto::GetMultiUserInfoRsp resp;
        im_proto::UserService_Stub stub(channel.get());
        stub.GetMultiUserInfo(&ctl, &req, &resp, nullptr);
        if(ctl.Failed() || !resp.success()) {
            LOG_ERROR("{}-{} 获取批量用户信息失败!", rid, ctl.ErrorText());
            return false;
        } 
        respUserInfoMap = resp.users_info();
        return true;
    }
    template<class Resp>
    void errResp(Resp* response, const std::string& errmsg) {
        response->set_success(false);
        response->set_errmsg(errmsg);
    }
private:
    shared::infra::DMSClientPtr dmsClient_; // 短信验证码平台

    shared::dal::UserSearchPtr esUser_;     // 用户搜索引擎对象

    shared::dal::ChatSessionDaoPtr chatSessionDao_;       // 持久化数据的操作对象
    shared::dal::ChatSessionMemberDaoPtr chatSessionMemberDao_;       // 持久化数据的操作对象
    shared::dal::UserRelationDaoPtr userRelationDao_;       // 持久化数据的操作对象
    shared::dal::FriendApplyDaoPtr friendApplyDao_;       // 持久化数据的操作对象

    shared::infra::RpcServiceManagerPtr rpcServiceMgr_;     // rpc的服务管理对象

    std::string userServiceName_;      // 用户子服务名称, 通过rpc获取用户信息
    std::string messageServiceName_;   // 消息子服务名称
};

class FriendServer
{
public:
    FriendServer(const shared::dal::ESClientPtr& esClient,
        const shared::dal::OdbPtr& mysqlClient,
        const shared::infra::DiscoveryPtr& rpcSvrDisc,
        const shared::infra::RegistrantPtr& rpcSvrRegist, 
        const std::shared_ptr<brpc::Server>& rpcServer)
        : esClient_(esClient), mysqlClient_(mysqlClient)
        , rpcSvrDisc_(rpcSvrDisc), rpcSvrRegist_(rpcSvrRegist), rpcServer_(rpcServer) {}
    ~FriendServer() {}
    void start() { rpcServer_->RunUntilAskedToQuit(); }

private:
    shared::dal::ESClientPtr esClient_;     // 支撑用户业务功能的搜索引擎句柄
    shared::dal::OdbPtr mysqlClient_;       // 用户数据的持久化句柄

    // 这三个对象都不是直接面向业务功能的, 而是为业务功能提供支撑
    // 因此服务没有结束, 这三个对象就不能释放, 于是放在FriendServer中
    std::shared_ptr<brpc::Server> rpcServer_;        // rpc服务器
    shared::infra::DiscoveryPtr rpcSvrDisc_;         // rpc服务发现对象
    shared::infra::RegistrantPtr rpcSvrRegist_;      // rpc服务注册对象
};

class FriendServerBuilder
{
public:
    // 构造搜索引擎对象
    void makeESObject(const std::vector<std::string>& hostList)
    {
        esClient_ = shared::dal::ESClientFactory::create(hostList);
    }
    // 构造odb-mysql客户端对象
    void makeMysqlObject(const std::string& Friend,  const std::string& passwd, 
        const std::string& host, const std::string& db,
        const std::string& cset, uint16_t port, uint16_t connectPoolCount)
    {
        mysqlClient_ = shared::dal::ODBFactory::create(
            Friend, passwd, host, db, cset, port, connectPoolCount
        );
    }
    // 构造Rpc服务注册客户端对象
    void makeRpcSvrRegistrant(const std::string& host, const std::string& serviceName, const std::string& accessHost)
    {
        rpcSvrRegist_ = std::make_shared<shared::infra::Registrant>(host);
        rpcSvrRegist_->registry(serviceName, accessHost);
    }
    // 构造Rpc服务发现客户端对象
    void makeRpcSvrDiscoverer(const std::string& host, const std::string& baseServiceName, const std::string& userServiceName, const std::string& msgServiceName)
    {
        // 用户管理子服务中需要关注文件子服务, 用于上传下载用户头像数据
        userServiceName_ = userServiceName;     
        messageServiceName_ = msgServiceName;     
        rpcServiceMgr_ = std::make_shared<shared::infra::RpcServiceManager>();
        rpcServiceMgr_->declared(userServiceName);
        rpcServiceMgr_->declared(msgServiceName);

        auto putCb = std::bind(
            &shared::infra::RpcServiceManager::onServiceOnline, rpcServiceMgr_.get(),
            std::placeholders::_1, std::placeholders::_2
        );
        auto delCb = std::bind(
            &shared::infra::RpcServiceManager::onServiceOffline, rpcServiceMgr_.get(),
            std::placeholders::_1, std::placeholders::_2
        );
        rpcSvrDisc_ = std::make_shared<shared::infra::Discovery>(host, baseServiceName, putCb, delCb);
    }
    // 构造RPC服务器对象
    void makeRpcServer(uint16_t port, int32_t timeout, uint8_t numThreads)
    {
        if (!esClient_) {
            LOG_ERROR("还未初始化ES搜索引擎模块!");
            abort();
        }
        if (!mysqlClient_) {
            LOG_ERROR("还未初始化mysql持久化模块!");
            abort();
        }
        if (!rpcServiceMgr_) {
            LOG_ERROR("还未初始化rpc服务管理模块!");
            abort();
        }
        rpcServer_ = std::make_shared<brpc::Server>();
        
        // 向rpc服务器添加服务实现类
        FriendServiceImpl* friendServiceImpl = new FriendServiceImpl(
            esClient_, mysqlClient_, rpcServiceMgr_, userServiceName_, messageServiceName_
        );
        if(rpcServer_->AddService(friendServiceImpl, brpc::ServiceOwnership::SERVER_OWNS_SERVICE) == -1) {
            LOG_ERROR("添加Rpc服务失败!");
            abort();
        }
        // 启动服务器
        brpc::ServerOptions options;    
        options.idle_timeout_sec = timeout;  
        options.num_threads = numThreads;        
        if(rpcServer_->Start(port, &options) == -1) {
            LOG_ERROR("Rpc服务启动失败!");
            abort();
        }
    }
    FriendServerPtr build()
    {
        if(!rpcSvrDisc_) {
            LOG_ERROR("还未初始化服务发现模块!");
            abort();
        }
        if (!rpcSvrRegist_) {
            LOG_ERROR("还未初始化服务注册模块!");
            abort();
        }
        if (!rpcServer_) {
            LOG_ERROR("还未初始化RPC服务器模块!");
            abort();
        }
        return std::make_shared<FriendServer>(
            esClient_, mysqlClient_, rpcSvrDisc_, rpcSvrRegist_, rpcServer_
        );
    }
private:
    shared::dal::ESClientPtr esClient_;     // 支撑用户业务功能的搜索引擎句柄
    shared::dal::OdbPtr mysqlClient_;       // 用户数据的持久化句柄

    std::shared_ptr<brpc::Server> rpcServer_;               // rpc服务器
    shared::infra::RpcServiceManagerPtr rpcServiceMgr_;     // rpc的服务管理对象
    shared::infra::RegistrantPtr rpcSvrRegist_;             // rpc服务注册对象
    shared::infra::DiscoveryPtr rpcSvrDisc_;                // rpc服务发现对象
    
    std::string userServiceName_;      // 用户子服务名称, 通过rpc获取用户信息
    std::string messageServiceName_;   // 消息子服务名称
};

}